package blazingbubble.gui.panels;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;

import moltencore.game.Game.Mode;

import blazingbubble.game.ILobbyGameEventListener;
import blazingbubble.graphics.game.IJoinGameListener;
import blazingbubble.graphics.lobby.IGameListUpdateListener;
import blazingbubble.gui.INavigationButton;
import blazingbubble.gui.ISwitchable;
import blazingbubble.gui.PanelRegistry;
import blazingbubble.gui.Resources;
import blazingbubble.gui.elements.MenuButton;
import blazingbubble.gui.elements.MenuTable;
import blazingbubble.network.game.strategy.IJoinGameResponseResultListener;

public class BrowseGamesPanel extends JPanel implements ActionListener, IGameListUpdateListener{
	private static final long serialVersionUID = 5134441426840957791L;
	
	public static final String PANEL_NAME = "BrowseGames";
	
	public static final Image BACKGROUND_IMAGE = Toolkit.getDefaultToolkit().createImage(Resources.BACKGROUND_NOTITLE_LARGE_IMAGEPATH);
	
	
	
	private static final String[] tableColumnNames = {
		"Game Name",
		"Players",
		"Game Mode",
		"b/g/r/b/c/g/w/f/t"};
	
	private ISwitchable parentFrame = null;
	
	private MenuButton refreshButton = new MenuButton(Resources.REFRESHBUTTON_IMAGEPATH);
	private MenuButton joinButton = new MenuButton(Resources.JOINGAME_SMALL_IMAGEPATH);
	private MenuButton backButton = new MenuButton(Resources.BACKBUTTON_MEDIUM_IMAGEPATH);
	
	private HashMap<Integer, Integer> gameTeamsCountMap = new HashMap<Integer, Integer>();
	private HashMap<Integer, Integer> gameTeamsSizeMap = new HashMap<Integer, Integer>();
	private HashMap<Integer, Integer> gameTablePortsMap = new HashMap<Integer, Integer>();
	
	private JScrollPane tablePane = null;
	private MenuTable gameTable = null;
	private DefaultTableModel gameTableModel = null;
	
	private IJoinGameListener joinGameListener = null;
	private ILobbyGameEventListener lobbyGameEventListener = null;
	
	private GameLobbyPanel gameLobbyPanel = null;

	private boolean isReceiving = false;
	
	public BrowseGamesPanel(ISwitchable parentFrame){
		this.parentFrame = parentFrame;
		PanelRegistry.getInstance().registerPanel(PANEL_NAME, this);
		setUp();
	}
	
	private void setUp(){
		this.setSize(500, 500);
		this.setLayout(null);
		
		gameLobbyPanel = new GameLobbyPanel(parentFrame);
		
		gameTableModel = new DefaultTableModel(null, tableColumnNames);
		gameTable = new MenuTable(gameTableModel, Font.PLAIN, 12);
		tablePane = new JScrollPane(gameTable);
		this.add(tablePane);
		tablePane.setBounds(5, 5, 485, 415);
		
		backButton.addActionListener(this);
		backButton.setDestinationPanel(PanelRegistry.getInstance().lookUpPanel(JoinGamePanel.PANEL_NAME));
		this.add(backButton);
		backButton.setBounds(5, 425, 160, 40);
		
		refreshButton.addActionListener(this);
		this.add(refreshButton);
		refreshButton.setBounds(165, 425, 160, 40);
		
		joinButton.addActionListener(this);
		this.add(joinButton);
		joinButton.setBounds(330, 425, 160, 40);		
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		if (event.getSource().equals(backButton)){
			parentFrame.switchSize(350, 450);
			parentFrame.switchPanel(((INavigationButton)event.getSource()).getDestinationPanel());
		}
		else if (event.getSource().equals(joinButton)){
			if (gameTable.getSelectedRow() != -1){
				joinGameListener.gameJoined(
						gameTeamsCountMap.get(gameTablePortsMap.get(gameTable.getSelectedRow())),
						gameTeamsSizeMap.get(gameTablePortsMap.get(gameTable.getSelectedRow())));
				System.out.println("calling selected");
				lobbyGameEventListener.gameSelected(gameTablePortsMap.get(gameTable.getSelectedRow()));
				System.out.println("done calling selected");
				parentFrame.getGameCommandFactory().getJoinGame().join();
				finishUpdating();
			}
		}
		else if (event.getSource().equals(refreshButton)) {
			if (isReceiving) {
				finishUpdating();
			} 
			else {
				refreshButton.swapImage(Resources.STOPREFRESHBUTTON_IMAGEPATH);
				isReceiving = true;
				clearTableData();
				parentFrame.getLobbyCommandFactory().getGameList().requestGameList();
			}
		}
		
		// TODO: handle refresh request, handle join game request
		
	}

	@Override
	public void addGame(int gamePort, int currentPlayers, int maxPlayers,
			int normalBubbleCount, boolean ghostBubblesEnabled,
			boolean rainbowBubblesEnabled, boolean blazingBubblesEnabled,
			boolean chainReactionsEnabled, boolean gravityEnabled,
			boolean windEnabled, boolean fieldFlipped, Mode mode,
			boolean teamsEnabled, String gameName) {
		
		int teamSize = teamsEnabled ? 2 : 1;
		gameTeamsSizeMap.put(gamePort, teamSize);
		gameTeamsCountMap.put(gamePort, maxPlayers / teamSize);
		gameTablePortsMap.put(gameTableModel.getRowCount(), gamePort);
		gameTableModel.insertRow(gameTableModel.getRowCount(),
					new Object[] {
				gameName,
				currentPlayers + "/" + maxPlayers,
				mode,
				normalBubbleCount + "/" +
				(ghostBubblesEnabled ? "x" : "o") + "/" +
				(rainbowBubblesEnabled ? "x" : "o") + "/" +
				(blazingBubblesEnabled ? "x" : "o") + "/" +
				(gravityEnabled ? "x" : "o") + "/" +
				(windEnabled ? "x" : "o") + "/" +
				(fieldFlipped ? "x" : "o") + "/" +
				(teamsEnabled ? "x" : "o")});		
	}

	@Override
	public void finishUpdating() {
		isReceiving = false;
		refreshButton.swapImage(Resources.REFRESHBUTTON_IMAGEPATH);		
	}

	@Override
	public boolean isReceiving() {
		return isReceiving;
	}
	
	public IJoinGameListener getJoinGameListener() {
		return joinGameListener;
	}

	public void setJoinGameListener(IJoinGameListener l) {
		joinGameListener = l;
	}
	
	public ILobbyGameEventListener getLobbyGameEventListener() {
		return lobbyGameEventListener;
	}

	public void setLobbyGameEventListener(
			ILobbyGameEventListener lobbyGameEventListener) {
		this.lobbyGameEventListener = lobbyGameEventListener;
	}
	
	private void clearTableData(){
		for (int i = 0; i < gameTableModel.getRowCount(); i++){
			gameTableModel.removeRow(0);
		}
	}
	
	@Override
	public void paintComponent(Graphics graphics) {
		super.paintComponent(graphics);
		graphics.drawImage(BACKGROUND_IMAGE, 0, 0, getWidth(), getHeight(), this);
	}
}
